package ivr

import (
	"github.com/beevik/etree"
	"strconv"
)

type (
	// Action IVR 菜单执行动作
	Action string

	MenuOption  func(e *etree.Element)
	EntryOption func(e *etree.Element)
)

const (
	// ActionExecApp 执行 app
	ActionExecApp Action = "menu-exec-app"
	// ActionPlaySound 播放音频
	ActionPlaySound Action = "menu-play-sound"
	// ActionSub 执行下级菜单
	ActionSub Action = "menu-sub"
	// ActionBack 返回上级菜单
	ActionBack Action = "menu-back"
	// ActionTop 返回顶级菜单
	ActionTop Action = "menu-top"
	// ActionExit 退出菜单
	ActionExit Action = "menu-exit"
)

// CreateMenu 创建 IVR 菜单
// digitLen: 最大收号位数
func CreateMenu(name string, digitLen uint64, opts ...MenuOption) *etree.Element {
	menu := etree.NewElement("menu")
	menu.CreateAttr("name", name)
	menu.CreateAttr("digit-len", strconv.FormatUint(digitLen, 10))
	menu.CreateAttr("timeout", "3000")
	menu.CreateAttr("inter-digit-timeout", "3000")
	menu.CreateAttr("max-failures", "3")
	menu.CreateAttr("max-timeouts", "3")

	for _, opt := range opts {
		opt(menu)
	}
	return menu
}

// CreateEntry 创建 创建 IVR 菜单执行入口
// digits: 匹配按键 可以是正则
// action: 执行动作
func CreateEntry(digits string, action Action, opts ...EntryOption) *etree.Element {
	entry := etree.NewElement("entry")
	entry.CreateAttr("digits", digits)
	entry.CreateAttr("action", string(action))

	for _, opt := range opts {
		opt(entry)
	}
	return entry
}

// WithTimeout 超时时间（毫秒）即多长时间没有收到按键就超时，播放其他提示音
func WithTimeout(t uint64) MenuOption {
	return func(menu *etree.Element) {
		menu.CreateAttr("timeout", strconv.FormatUint(t, 10))
	}
}

// WithInterDigitTimeout 两次按键的最大间隔（毫秒）
func WithInterDigitTimeout(t uint64) MenuOption {
	return func(menu *etree.Element) {
		menu.CreateAttr("inter-digit-timeout", strconv.FormatUint(t, 10))
	}
}

// WithGreetLong 欢迎提示音(进入菜单时播放)
func WithGreetLong(f string) MenuOption {
	return func(menu *etree.Element) {
		menu.CreateAttr("greet-long", f)
	}
}

// WithGreetShort 简短欢迎词(长时间没按键的简短提示音文件)
func WithGreetShort(f string) MenuOption {
	return func(menu *etree.Element) {
		menu.CreateAttr("greet-short", f)
	}
}

// WithInvalidSound 按键错误提示音
func WithInvalidSound(f string) MenuOption {
	return func(menu *etree.Element) {
		menu.CreateAttr("invalid-sound", f)
	}
}

// WithExitSound 菜单退出提示音
func WithExitSound(f string) MenuOption {
	return func(menu *etree.Element) {
		menu.CreateAttr("exit-sound", f)
	}
}

// WithMaxFailures 按键错误最大次数
func WithMaxFailures(n uint64) MenuOption {
	return func(menu *etree.Element) {
		menu.CreateAttr("max-failures", strconv.FormatUint(n, 10))
	}
}

// WithMaxTimeouts 最大超时次数
func WithMaxTimeouts(n uint64) MenuOption {
	return func(menu *etree.Element) {
		menu.CreateAttr("max-timeouts", strconv.FormatUint(n, 10))
	}
}

// WithActionParam 执行参数
func WithActionParam(p string) EntryOption {
	return func(entry *etree.Element) {
		entry.CreateAttr("param", p)
	}
}
